// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/Character.h"
#include "PerceptionNotify.h"
#include "RootZombieBase.generated.h"

#define NormalSight 400.0f
#define AngrySight 800.0f

#define LookBackOffset 200.0f

#define Action_Free 0
#define Action_Search 1
#define Action_Attack 2

UCLASS()
class ISALONG2_API ARootZombieBase : public ACharacter ,public IBeHurtable , public IPerceptionNotify
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ARootZombieBase();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	// Called every frame
	virtual void Tick(float DeltaSeconds) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;

	// on hurt
	virtual void OnHurt(AActor* shotter, FVector impactNormal, FVector hitLocation, int HurtType, float hurtValue, UPrimitiveComponent* hitComponent);

	// on perception notify on
	virtual void PerceptionOutlineOn();

	virtual void PerceptionOutlineOff();

	// init anim info
	void InitInfo(USkeletalMesh* MainSkeletalMesh, TSubclassOf<UAnimInstance> ZombieAnimBP);

protected:
	UArrowComponent* _forwardArrow;

	// view sight
	USphereComponent* _viewSphere;

	// the box for attack actor detection
	UBoxComponent* _attackBox;

private:
	// anim switch
	bool _animEnable = true;
	// anim switch


	bool _isGoStraight = false;
	FVector _goStraightTargetDirection = FVector(1, 0, 0);

	// pathfinding
	FVector _destLocation; /* the dest location that for the pawn to reach */
	FVector _currentTaget; /* the current target separated the path the local target */
	bool _isMovingTo = false;
	TArray<FNavPathPoint> _path;
	int _pathPointer; /* always point to the current point */

					  // indicate whether is turning or not
	bool _isTurning = false;
	bool _isAttackReloading = false;

	TArray<AActor*> _roiActor; /* the roi actor  */
	float _attention = 0; /* the attention drive the zombie`s action */
	int _currentAction = 0; /* the action that the Ai current hold */
	float _currentSightSphereSize = NormalSight;

	TArray<FHitResult> _preAttackActor; /* Pre attack actor. recode */

	UAnimMontage* _turnL90;
	UAnimMontage* _turnL180;
	UAnimMontage* _turnR90;
	UAnimMontage* _turnR180;

	UAnimMontage* _hurtFront;
	UAnimMontage* _hurtBack;
	UAnimMontage* _hurtLeft;
	UAnimMontage* _hurtRight;

	UAnimMontage* _attack1;
	UAnimMontage* _attack2;
	UAnimMontage* _attack3;

	float _lifeValue = 1.0f;

	//////////////////////////////////////////////////////////////////////////
	//						Free Param start								//
	//////////////////////////////////////////////////////////////////////////

	float _free_selectNewPointTime = 20.0f;
	float _free_selectNewPointTimeRemain = 0.0f;
	float _free_idleTime = 6.0f;
	float _free_idleTimeRemain = 0.0f;
	bool _free_choose = false; // false select point ,true idle
	FVector _freeTargetDirection;

	void FreeRandom();

	//////////////////////////////////////////////////////////////////////////
	//							Free Param End								//
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	//							Attack Param Start							//
	//////////////////////////////////////////////////////////////////////////

	AActor* _attack_target = nullptr;
	float _attack_hurtValue = 0.6f;

	//////////////////////////////////////////////////////////////////////////
	//							Attack Param End							//
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	//							Search Param Start							//
	//////////////////////////////////////////////////////////////////////////

	float _search_timestime = 6.0f;
	float _search_timestimeRemain = 0.0f;
	float _search_randomAngle = 0;

	//////////////////////////////////////////////////////////////////////////
	//							Search Param End							//
	//////////////////////////////////////////////////////////////////////////
private:
	void GoStraightTick(float DeltaTime);

	void MoveToTick(float DeltaTime);

	void StateCheckTick(float DeltaTime);

	void FreeTick(float DeltaTime);

	void SearchTick(float DeltaTime);

	void AttackTick(float DeltaTime);

private:
	void AddAttention(float val);

	void DoAction(int action);

	bool InSight(AActor* actor);

	void SetSightSphereSize(float val);

	void Die();

	// action API
public:
	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void MoveForward();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void StopMoveForward();

	// add rotation on moveforward
	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void GoStraight(FVector direction);

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void StopStraight();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void TurnRight90();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void TurnRight180();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void TurnLeft90();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void TurnLeft180();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void TurnComplete();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void HurtBack();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void Attack();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void AttackAnimComplete();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void AttackFire();

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void MoveTo(FVector destLocation, bool usePathFinding = true);

	UFUNCTION(BlueprintCallable, category = "ActionAPI")
	void StopMoveTo();

private:
	// for ai attation or state translate
	UFUNCTION()
	void OnROIBeginOverlap( AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnROIEndOverlap( AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	UFUNCTION()
	void OnPreAttackActorBeginOverlap(AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnPreAttackActorEndOverlap(AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
	// state
public:
	UPROPERTY(BlueprintReadOnly, category = "State")
		bool _isMovingForward;

	UPROPERTY(BlueprintReadOnly, category = "State")
		bool _isShamble;
};
